﻿using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;

using System.Windows.Media;
using System.Windows.Media.Effects;
using System.Diagnostics;
using System.Reflection;

namespace PermDoc.GDI
{

    public class RippleEffect : ShaderEffect
    {
        /// <summary>
        /// Gets or sets the Center variable within the shader.
        /// </summary>
        public static readonly DependencyProperty CenterProperty = DependencyProperty.Register("Center", typeof(Point), typeof(RippleEffect), new PropertyMetadata(new Point(0.5, 0.5), PixelShaderConstantCallback(0)));

        /// <summary>
        /// Gets or sets the Amplitude variable within the shader.
        /// </summary>
        public static readonly DependencyProperty AmplitudeProperty = DependencyProperty.Register("Amplitude", typeof(double), typeof(RippleEffect), new PropertyMetadata(0.1, PixelShaderConstantCallback(1)));

        /// <summary>
        /// Gets or sets the Frequency variable within the shader.
        /// </summary>
        public static readonly DependencyProperty FrequencyProperty = DependencyProperty.Register("Frequency", typeof(double), typeof(RippleEffect), new PropertyMetadata(50.0, PixelShaderConstantCallback(2)));

        /// <summary>
        /// Gets or sets the Phase variable within the shader.
        /// </summary>
        public static readonly DependencyProperty PhaseProperty = DependencyProperty.Register("Phase", typeof(double), typeof(RippleEffect), new PropertyMetadata(0.0, PixelShaderConstantCallback(3)));

        /// <summary>
        /// Gets or sets the input brush used in the shader.
        /// </summary>
        public static readonly DependencyProperty InputProperty = ShaderEffect.RegisterPixelShaderSamplerProperty("Input", typeof(RippleEffect), 0);

        /// <summary>
        /// The pixel shader instance.
        /// </summary>
        private static PixelShader pixelShader;

        /// <summary>
        /// Creates an instance of the shader from the included pixel shader.
        /// </summary>
        static RippleEffect()
        {

            pixelShader = new PixelShader();
            pixelShader.UriSource = new Uri("ShaderBytecode/Ripple.fx.ps", UriKind.RelativeOrAbsolute);

        }

        /// <summary>
        /// Creates an instance and updates the shader's variables to the default values.
        /// </summary>
        public RippleEffect()
        {
            this.PixelShader = pixelShader;

            UpdateShaderValue(CenterProperty);
            UpdateShaderValue(AmplitudeProperty);
            UpdateShaderValue(PhaseProperty);
            UpdateShaderValue(FrequencyProperty);
            UpdateShaderValue(InputProperty);
        }

        /// <summary>
        /// Gets or sets the center variable within the shader.
        /// </summary>
        public Point Center
        {
            get { return (Point)GetValue(CenterProperty); }
            set { SetValue(CenterProperty, value); }
        }

        /// <summary>
        /// Gets or sets the Amplitude variable within the shader.
        /// </summary>
        public double Amplitude
        {
            get { return (double)GetValue(AmplitudeProperty); }
            set { SetValue(AmplitudeProperty, value); }
        }

        /// <summary>
        /// Gets or sets the frequency variable within the shader.
        /// </summary>
        public double Frequency
        {
            get { return (double)GetValue(FrequencyProperty); }
            set { SetValue(FrequencyProperty, value); }
        }

        /// <summary>
        /// Gets or sets the Phase variable within the shader.
        /// </summary>
        public double Phase
        {
            get { return (double)GetValue(PhaseProperty); }
            set { SetValue(PhaseProperty, value); }
        }

        /// <summary>
        /// Gets or sets the input used within the shader.
        /// </summary>
        public Brush Input
        {
            get { return (Brush)GetValue(InputProperty); }
            set { SetValue(InputProperty, value); }
        }
    }
    
    public class SmoothMagnifyEffect : ShaderEffect
    {
        /// <summary>
        /// Gets or sets the Center variable within the shader.
        /// </summary>
        public static readonly DependencyProperty CenterProperty = DependencyProperty.Register("Center", typeof(Point), typeof(SmoothMagnifyEffect), new PropertyMetadata(new Point(0.5, 0.5), PixelShaderConstantCallback(0)));

        /// <summary>
        /// Gets or sets the InnerRadius variable within the shader.
        /// </summary>
        public static readonly DependencyProperty InnerRadiusProperty = DependencyProperty.Register("InnerRadius", typeof(double), typeof(SmoothMagnifyEffect), new PropertyMetadata(.2, PixelShaderConstantCallback(2)));

        /// <summary>
        /// Gets or sets the Magnification variable within the shader.
        /// </summary>
        public static readonly DependencyProperty MagnificationProperty = DependencyProperty.Register("Magnification", typeof(double), typeof(SmoothMagnifyEffect), new PropertyMetadata(2.0, PixelShaderConstantCallback(3)));

        /// <summary>
        /// Gets or sets the OuterRaduis variable within the shader.
        /// </summary>
        public static readonly DependencyProperty OuterRadiusProperty = DependencyProperty.Register("OuterRadius", typeof(double), typeof(SmoothMagnifyEffect), new PropertyMetadata(.27, PixelShaderConstantCallback(4)));

        /// <summary>
        /// Gets or sets the input brush used in the shader.
        /// </summary>
        public static readonly DependencyProperty InputProperty = ShaderEffect.RegisterPixelShaderSamplerProperty("Input", typeof(SmoothMagnifyEffect), 0);

        /// <summary>
        /// The pixel shader instance.
        /// </summary>
        private static PixelShader pixelShader;

        /// <summary>
        /// Creates an instance of the shader from the included pixel shader.
        /// </summary>
        static SmoothMagnifyEffect()
        {
            pixelShader = new PixelShader();
            pixelShader.UriSource = new Uri("ShaderBytecode/smoothmagnify.fx.ps", UriKind.RelativeOrAbsolute);
        }

        /// <summary>
        /// Creates an instance and updates the shader's variables to the default values.
        /// </summary>
        public SmoothMagnifyEffect()
        {
            this.PixelShader = pixelShader;

            UpdateShaderValue(CenterProperty);
            UpdateShaderValue(InnerRadiusProperty);
            UpdateShaderValue(OuterRadiusProperty);
            UpdateShaderValue(MagnificationProperty);
            UpdateShaderValue(InputProperty);
        }

        /// <summary>
        /// Gets or sets the center variable within the shader.
        /// </summary>
        public Point Center
        {
            get { return (Point)GetValue(CenterProperty); }
            set { SetValue(CenterProperty, value); }
        }

        /// <summary>
        /// Gets or sets the InnerRadius variable within the shader.
        /// </summary>
        public double InnerRadius
        {
            get { return (double)GetValue(InnerRadiusProperty); }
            set { SetValue(InnerRadiusProperty, value); }
        }

        /// <summary>
        /// Gets or sets the Magnification variable within the shader.
        /// </summary>
        public double Magnification
        {
            get { return (double)GetValue(MagnificationProperty); }
            set { SetValue(MagnificationProperty, value); }
        }

        /// <summary>
        /// Gets or sets the OuterRadius variable within the shader.
        /// </summary>
        public double OuterRadius
        {
            get { return (double)GetValue(OuterRadiusProperty); }
            set { SetValue(OuterRadiusProperty, value); }
        }

        /// <summary>
        /// Gets or sets the input brush used within the shader.
        /// </summary>
        public Brush Input
        {
            get { return (Brush)GetValue(InputProperty); }
            set { SetValue(InputProperty, value); }
        }
    }

    public class ColorKeyAlphaEffect : ShaderEffect
    {

        /// <summary>
        /// This property is mapped to the InputColor variable within the pixel shader.
        /// </summary>
        public static readonly DependencyProperty ColorKeyProperty = DependencyProperty.Register("ColorKey", typeof(Color), typeof(ColorKeyAlphaEffect), new PropertyMetadata(Colors.Green, PixelShaderConstantCallback(0)));

        /// <summary>
        /// The explict input for this pixel shader.
        /// </summary>
        public static readonly DependencyProperty InputProperty = ShaderEffect.RegisterPixelShaderSamplerProperty("Input", typeof(ColorKeyAlphaEffect), 0);

        /// <summary>
        /// A reference to the pixel shader used.
        /// </summary>
        private static PixelShader pixelShader;

        /// <summary>
        /// Creates an instance of the shader from the included pixel shader.
        /// </summary>
        static ColorKeyAlphaEffect()
        {
            pixelShader = new PixelShader();
            pixelShader.UriSource = new Uri("ShaderBytecode/ColorKeyAlpha.fx.ps", UriKind.RelativeOrAbsolute);
        }

        /// <summary>
        /// Creates an instance and updates the shader's variables to the default values.
        /// </summary>
        public ColorKeyAlphaEffect()
        {
            this.PixelShader = pixelShader;

            UpdateShaderValue(ColorKeyProperty);
            UpdateShaderValue(InputProperty);
        }

        /// <summary>
        /// Gets or sets the InputColor variable within the shader.
        /// </summary>
        public Color ColorKey
        {
            get { return (Color)GetValue(ColorKeyProperty); }
            set { SetValue(ColorKeyProperty, value); }
        }

        /// <summary>
        /// Gets or sets the Input of shader.
        /// </summary>
        public Brush Input
        {
            get { return (Brush)GetValue(InputProperty); }
            set { SetValue(InputProperty, value); }
        }
    }

}
